﻿/*
 * ©2009-2010 XELF
 * http://xelf.info
 */

#if XNA || WINDOWS_PHONE
using Microsoft.Xna.Framework;
using Vector4Helper = Microsoft.Xna.Framework.Vector4;
#else
using Vector4Helper = XELF.Framework.Vector4;
#endif

namespace XELF.Framework {
#if XNA || WINDOWS_PHONE
	public static partial class MatrixHelper {
#else
	public partial struct Matrix {
#endif
		/// <summary>
		/// ビュー行列を作る。
		/// </summary>
		/// <param name="cameraPosition">カメラの位置</param>
		/// <param name="cameraTarget">カメラを向ける対象位置</param>
		/// <param name="cameraUpVector">カメラの上の方向</param>
		/// <param name="result"></param>
		public static void CreateLookAt(
			ref Vector3 cameraPosition, ref Vector3 cameraTarget, ref Vector3 cameraUpVector, out Matrix result) {
			Vector3 direction;
			Vector3.Subtract(ref cameraPosition, ref cameraTarget, out direction);
			direction.Normalize();
			cameraUpVector.Normalize();
			Vector3 right;
			Vector3.Cross(ref cameraUpVector, ref direction, out right);
			right.Normalize();
			Vector3.Cross(ref direction, ref right, out cameraUpVector);
			cameraUpVector.Normalize();
			result = new Matrix(
				right.X, cameraUpVector.X, direction.X, 0,
				right.Y, cameraUpVector.Y, direction.Y, 0,
				right.Z, cameraUpVector.Z, direction.Z, 0,
				0, 0, 0, 1);
			Vector4 position = new Vector4(cameraPosition, 1);
			Vector4 translation;
			Vector4Helper.TransformCoordinate(ref position, ref result, out translation);
			result.M41 = -translation.X;
			result.M42 = -translation.Y;
			result.M43 = -translation.Z;
			result.M44 = +translation.W;
		}
		/// <summary>
		/// ビュー行列を作る。
		/// </summary>
		/// <param name="cameraPosition"></param>
		/// <param name="cameraTarget"></param>
		/// <param name="cameraUpVector"></param>
		/// <returns></returns>
		public static Matrix CreateLookAt(Vector3 cameraPosition, Vector3 cameraTarget, Vector3 cameraUpVector) {
			Matrix result;
			CreateLookAt(ref cameraPosition, ref cameraTarget, ref cameraUpVector, out result);
			return result;
		}
	}

}
